/**
  ******************************************************************************
  * @file    User/i2c1_bus.c
  * @date    18-Mar-2018
  * @brief   gpio config and simulation i2c1 operating functions
  ******************************************************************************
  */
  
#include "i2c1_bus.h"

static GPIO_InitTypeDef i2c1GPIOInitStruct;

void I2c1_Bus_Init(void)
{
	I2C1_Init(0);		// parameter is unused
}

static void I2C1_Init(uint32_t clkSpeed)
{	
	I2C1_GPIO_CLK_CMD(I2C1_GPIO_CLK, ENABLE);
	i2c1GPIOInitStruct.GPIO_Pin = I2C1_SCL_PIN;
	i2c1GPIOInitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
	i2c1GPIOInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(I2C1_SCL_PORT, &i2c1GPIOInitStruct);
	i2c1GPIOInitStruct.GPIO_Pin = I2C1_SDA_PIN;
	GPIO_Init(I2C1_SDA_PORT, &i2c1GPIOInitStruct);
	GPIO_SetBits(I2C1_SCL_PORT, I2C1_SCL_PIN);
	GPIO_SetBits(I2C1_SDA_PORT, I2C1_SDA_PIN);
}

static void I2C1_Start(void)
{
	I2C1_SDA_HIGH;
	I2C1_SCL_HIGH;
	delay_us(I2C1_DELAY);
	I2C1_SDA_LOW;
	delay_us(I2C1_DELAY);
	I2C1_SCL_LOW;
	delay_us(I2C1_DELAY);
}

static void I2C1_Stop(void)
{
	I2C1_SCL_LOW;
	I2C1_SDA_LOW;
	delay_us(I2C1_DELAY);
	I2C1_SCL_HIGH;
	delay_us(I2C1_DELAY);
	I2C1_SDA_HIGH;
	delay_us(I2C1_DELAY);
}

static void I2C1_SendACK(uint8_t ack)
{
	I2C1_SCL_LOW;
	delay_us(I2C1_DELAY);
	I2C1_SDA(ack);
	delay_us(I2C1_DELAY);
	I2C1_SCL_HIGH;
	delay_us(I2C1_DELAY);
	I2C1_SCL_LOW;
	delay_us(I2C1_DELAY);
}

static uint8_t I2C1_WaitACK(void)
{
	uint8_t ackSignal;
	I2C1_SCL_LOW;
	delay_us(I2C1_DELAY);
	I2C1_SDA_HIGH;
	delay_us(I2C1_DELAY);
	I2C1_SCL_HIGH;
	delay_us(I2C1_DELAY);
	I2C1_SDAin;
	delay_us(I2C1_DELAY);
	ackSignal = I2C1_SDA_READ;
	delay_us(I2C1_DELAY);
	I2C1_SDAout;
	delay_us(I2C1_DELAY);
	I2C1_SCL_LOW;
	delay_us(I2C1_DELAY);
	return ackSignal;
}

static void I2C1_SendByte(uint8_t data)
{
	uint8_t i;
	for (i=0; i<8; i++)
	{
		I2C1_SCL_LOW;
		delay_us(I2C1_DELAY);
		//I2C1_SDA(((data<<i) & 0x80)>>7);
		I2C1_SDA(data >> (7-i) & 0x01);
		delay_us(I2C1_DELAY);
		I2C1_SCL_HIGH;
		delay_us(I2C1_DELAY);
	}
	I2C1_SCL_LOW;
	delay_us(I2C1_DELAY);
}

static uint8_t I2C1_RecvByte(void)
{
	uint8_t i;
	uint8_t data = 0;
	I2C1_SDA_HIGH; 
	delay_us(I2C1_DELAY);
	I2C1_SDAin;
	delay_us(I2C1_DELAY);
	for (i=0; i<8; i++)
	{
		data <<= 1;
		I2C1_SCL_LOW;
		delay_us(I2C1_DELAY);
		I2C1_SCL_HIGH;
		delay_us(I2C1_DELAY);
		data |= I2C1_SDA_READ;
	}
	I2C1_SCL_LOW;
	delay_us(I2C1_DELAY);
	I2C1_SDAout;
	delay_us(I2C1_DELAY);
	return data;
}

uint8_t I2C1_WriteData(uint8_t devAddress, uint8_t regAddress, uint8_t *data, uint16_t length)
{
	uint16_t cnt;
	I2C1_Start();
	I2C1_SendByte(devAddress << 1 | 0);
	if(I2C1_WaitACK() == NACK_SIGNAL)
	{
		I2C1_Stop();
		return 1;
	}
	I2C1_SendByte(regAddress);
	if(I2C1_WaitACK() == NACK_SIGNAL)
	{
		I2C1_Stop();
		return 2;
	}
	for(cnt = 0; cnt < length; cnt++)
	{
		I2C1_SendByte(data[cnt]);
		if(I2C1_WaitACK() == NACK_SIGNAL)
		{
			I2C1_Stop();
			return 3;
		}
	}
	I2C1_Stop();
	return 0;
}

uint8_t I2C1_ReadData_8B_Addr(uint8_t devAddress, uint8_t regAddress, uint8_t *data, uint16_t length)
{
	uint16_t cnt;
	I2C1_Start();
	I2C1_SendByte(devAddress << 1 | 0);
	if(I2C1_WaitACK() == NACK_SIGNAL)
	{
		I2C1_Stop();
		return 1;
	}
	I2C1_SendByte(regAddress);
	if(I2C1_WaitACK() == NACK_SIGNAL)
	{
		I2C1_Stop();
		return 2;
	}
	I2C1_Start();
	I2C1_SendByte(devAddress << 1 | 1);
	if(I2C1_WaitACK() == NACK_SIGNAL)
	{
		I2C1_Stop();
		return 3;
	}
	for(cnt = 0; cnt < length; cnt++)
	{
		data[cnt] = I2C1_RecvByte();
		if(cnt == length-1)
		{

			I2C1_SendACK(NACK_SIGNAL);
		}
		else
		{
			I2C1_SendACK(ACK_SIGNAL);
		}
	}
	I2C1_Stop();
	return 0;
}

uint8_t I2C1_ReadData_16B_Addr(uint8_t devAddress, uint16_t command, uint8_t *data, uint16_t length)
{
	uint16_t cnt;
	I2C1_Start();
	I2C1_SendByte(devAddress << 1 | 0);
	if(I2C1_WaitACK() == NACK_SIGNAL)
	{
		I2C1_Stop();
		return 1;
	}
	I2C1_SendByte((command >> 8) & 0xff);
	if(I2C1_WaitACK() == NACK_SIGNAL)
	{
		I2C1_Stop();
		return 2;
	}
	I2C1_SendByte(command & 0xff);
	if(I2C1_WaitACK() == NACK_SIGNAL)
	{
		I2C1_Stop();
		return 2;
	}
	I2C1_Start();
	I2C1_SendByte(devAddress << 1 | 1);
	if(I2C1_WaitACK() == NACK_SIGNAL)
	{
		I2C1_Stop();
		return 3;
	}
	for(cnt = 0; cnt < length; cnt++)
	{
		data[cnt] = I2C1_RecvByte();
		if(cnt == length-1)
		{

			I2C1_SendACK(NACK_SIGNAL);
		}
		else
		{
			I2C1_SendACK(ACK_SIGNAL);
		}
	}
	I2C1_Stop();
	return 0;
}

uint8_t I2C1_ReadData_8B_Addr_NHMM(uint8_t devAddress, uint8_t regAddress, uint8_t *data, uint16_t length)
{
	uint16_t cnt;
	I2C1_Start();
	I2C1_SendByte(devAddress << 1 | 0);
	if(I2C1_WaitACK() == NACK_SIGNAL)
	{
		I2C1_Stop();
		return 1;
	}
	I2C1_SendByte(regAddress);
	if(I2C1_WaitACK() == NACK_SIGNAL)
	{
		I2C1_Stop();
		return 2;
	}
	I2C1_Start();
	I2C1_SendByte(devAddress << 1 | 1);
	// TODO:待优化，去除循环等待
	while(I2C1_WaitACK() == NACK_SIGNAL)
	{
		I2C1_Start();
		I2C1_SendByte(devAddress << 1 | 1);
		//I2C1_Stop();
		//return 3;
	}
	for(cnt = 0; cnt < length; cnt++)
	{
		data[cnt] = I2C1_RecvByte();
		if(cnt == length-1)
		{

			I2C1_SendACK(NACK_SIGNAL);
		}
		else
		{
			I2C1_SendACK(ACK_SIGNAL);
		}
	}
	I2C1_Stop();
	return 0;
}

uint8_t I2C1_CheckDev(uint8_t devAddress)
{
	uint8_t devAck = 0;
	I2C1_Start();
	I2C1_SendByte(devAddress << 1 | 0);
	devAck = I2C1_WaitACK();
	I2C1_Stop();
	return devAck;
}
